package com.example.design.demo.clone;

import java.io.*;

/**
 * @author lfj
 * @date 2023/11/24 17:25
 * @description 原型模式
 */
public class CloneDemoTest {
        public static void main(String[] args) {
            try {
                test05();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    /**
     * 测试克隆的对象与new出来的对象是否为同一个
     */
    public static void test01(){
            //产生一个对象
            PrototypeClass02 thing = new PrototypeClass02();
            //拷贝一个对象
            PrototypeClass02 cloneThing = thing.clone();
            //2、测试2个对象是否为同一个 结果为false
            System.out.println(cloneThing==thing);
        }

    /**
     * 测试克隆出来的对象是否执行构造方法
     * 那对象是怎么克隆出来的呢？
     * 内存?
     * clone方法的原理是从内存中（具体地说就是堆内存）以二进制流的方式进行拷贝，
     * 重新分配个内存块，那构造函数没有被执行也是非常正常的了。
     */
    public static void test02(){
        PrototypeClass01 thing = new PrototypeClass01();
        PrototypeClass01 cloneThing = thing.clone();
       //执行结果：执行构造函数啦 -只执行一次
    }

    /**
     * 浅克隆 --发现类中类并未完成克隆。而是复制了一份地址给新的对象
     *
     */
    public static void test03(){
        PrototypeClass02 thing = new PrototypeClass02();
        TestPrototype testPrototype = new TestPrototype();
        thing.setTestPrototype(testPrototype);

        PrototypeClass02 cloneThing = thing.clone();
        System.out.println(thing==cloneThing);
        System.out.println(thing.getTestPrototype() == cloneThing.getTestPrototype());
        //执行结果： false true
    }
    /**
     * 深克隆--重写clone方法
     * 很多时候浅克隆并不满足我们业务场景，所以衍生深克隆
     * 例如老师、学生组合的时候，我们多个班主任老师，对应的学生不可能是重复的，
     *
     */
    public static void test04(){
        PrototypeClass03 thing = new PrototypeClass03();
        TestPrototype testPrototype = new TestPrototype();
        thing.setTestPrototype(testPrototype);

        PrototypeClass03 cloneThing = thing.clone();
        System.out.println(thing==cloneThing);
        System.out.println(thing.getTestPrototype() == cloneThing.getTestPrototype());
        //执行结果： false false
    }
    /**
     * 深克隆--利用序列化的方式
     * 序列化可以通过反射创建新的对象，从而导致了单例模式的破坏，原型模式的需要
     * 通过使用序列化反序列化的方式我们可以完全的创建一个新的对象，
     * 而且这种方法会复制所有的变量类型，完全不需要担心类与类之间的嵌套组合。
     */
    public static void test05() throws Exception{
        PrototypeClass02  thing = new PrototypeClass02 ();
        TestPrototype testPrototype = new TestPrototype();
        thing.setTestPrototype(testPrototype);
        PrototypeClass02.outObject(thing);

        PrototypeClass02 cloneThing = PrototypeClass02.readObject();
        System.out.println(thing==cloneThing);
        System.out.println(thing.getTestPrototype() == cloneThing.getTestPrototype());
    }


}
